package jp.sourceforge.akjrcp.ffmpeg;

import com.akjava.lib.standards.process.ProcessMonitor;
import com.akjava.lib.standards.process.ProcessPrinter;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import jp.sourceforge.akjrcp.util.DoNothingProcessPrinter;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


/*
 * if problem happends.check ffmpeg options. 
 * 
 */
public class FFMpegJpegPipeWriter implements Runnable{
	public static Log log = LogFactory.getLog(FFMpegJpegPipeWriter.class);
	JpegPipeWriter jpegPipeWriter;
	private String[] command;
	private Process process;
	ProcessListener processListener;
	private long maxoverwait=10000; 
	private ProcessPrinter processPrinter=new DoNothingProcessPrinter();
	public ProcessPrinter getProcessPrinter() {
		return processPrinter;
	}

	public void setProcessPrinter(ProcessPrinter processPrinter) {
		this.processPrinter = processPrinter;
	}

	public FFMpegJpegPipeWriter(String ffmpegPath,boolean overwrite,String[] pipeInputOption,String[] outputOption,String outputPath){
		//TODO:use ArrayUtil
		List list=new ArrayList();
		for (int i = 0; i < outputOption.length; i++) {
			list.add(outputOption[i]);
		}
		list.add(outputPath);
		String options[]= (String[])list.toArray(new String[0]);
		command = FFMpegCommandUtil.makeInputPipeCommand(ffmpegPath, overwrite, pipeInputOption,options);
		log.info(FFMpegUtils.toPrintCommand(command));
	}
	
	public void run() {
		Runtime runtime=Runtime.getRuntime();
		try {
			process = runtime.exec(command);
			//SimpleProcessPrinter printer=new SimpleProcessPrinter();
			//PrintWriterPrinter printer=new PrintWriterPrinter(System.out);
			
			ProcessMonitor monitor=new ProcessMonitor(process,processPrinter);
			monitor.startMonitor();
			
			jpegPipeWriter=new JpegPipeWriter(process.getOutputStream());
			
			
			if(processListener!=null){
				processListener.started();
			}
			try {
				Thread.sleep(500);//magic sleep?
			} catch (InterruptedException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			try {
				process.waitFor();
				
				long c=System.currentTimeMillis();
				while(System.currentTimeMillis()<c+maxoverwait){
					if(monitor.isErrorClosed() && monitor.isInputClosed()){
						break;
					}else{
						log.warn("wait:input reading");
						Thread.sleep(100);
					}
				}
				
				if(processListener!=null){
					processListener.finished();
				}
				//process.destroy();//otherwise sometime stop.
				log.info("write process finished:"+process.exitValue());
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	}
	
	public void closeError(){
		if(process!=null){
			InputStream input=process.getErrorStream();
			if(input!=null){
				try {
					input.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
	}
	

	public void closeInput(){
		if(process!=null){
			InputStream input=process.getInputStream();
			if(input!=null){
				try {
					input.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
	}
	public void cancel(){
		if(process!=null){
			process.destroy();
		}
	}
	
	public void close() throws IOException{
		if(jpegPipeWriter!=null){
			jpegPipeWriter.close();
		}
	}

	public String[] getCommand() {
		return command;
	}

	public void setCommand(String[] command) {
		this.command = command;
	}

	public JpegPipeWriter getJpegPipeWriter() {
		return jpegPipeWriter;
	}

	public void setJpegPipeWriter(JpegPipeWriter jpegPipeWriter) {
		this.jpegPipeWriter = jpegPipeWriter;
	}

	public Process getProcess() {
		return process;
	}

	public void setProcess(Process process) {
		this.process = process;
	}

	public ProcessListener getProcessListener() {
		return processListener;
	}

	public void setProcessListener(ProcessListener processListener) {
		this.processListener = processListener;
	}
}
